package com.gzhryc.servlet;

import java.lang.reflect.Method;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gzhryc.common.PackageTools;
import com.gzhryc.servlet.annotation.Route;
import com.gzhryc.servlet.resources.VoidResource;

/**
 * HTTP处理程序的工厂
 * 
 * @author zhanghao
 * @version 2020-08-11
 */
public class HttpHandlerFactory {

	static Logger log = LoggerFactory.getLogger(HttpHandlerFactory.class);

	public static HttpHandler readHttpHandler(Class<?> clazz) {
		try {
			Object obj = clazz.newInstance();
			return readHttpHandler(null, obj, clazz);
		} catch (Exception e) {
			if(NoSuchMethodException.class.isInstance(e) || InstantiationException.class.isInstance(e)){
				log.error(e.getMessage() + " 未能创建类对象：" + clazz.getName());
			}else {
				log.error(e.getMessage(), e);
			}
		}
		return null;
	}

	public static HttpHandler readHttpHandler(HttpHandler handler, Class<?> clazz) {
		try {
			Object obj = clazz.newInstance();
			return readHttpHandler(handler, obj, clazz);
		} catch (Exception e) {
			if(NoSuchMethodException.class.isInstance(e) || InstantiationException.class.isInstance(e)){
				log.error(e.getMessage() + " 未能创建类对象：" + clazz.getName());
			}else {
				log.error(e.getMessage(), e);
			}
		}
		return null;
	}

	public static HttpHandler readHttpHandler(Object obj) {
		return readHttpHandler(null, obj, obj.getClass());
	}

	public static HttpHandler readHttpHandler(String packagePath) {
		HttpHandler result = null;
		List<String> classNames = PackageTools.getClassName(packagePath);
		for (String className : classNames) {
			try {
				Class<?> clazz = Class.forName(className);
				Object obj = clazz.newInstance();
				result = readHttpHandler(result, obj, clazz);
			}catch (Exception e) {
				if(NoSuchMethodException.class.isInstance(e) || InstantiationException.class.isInstance(e)){
					log.error(e.getMessage() + " 未能创建类对象：" + className);
				}else {
					log.error(e.getMessage(), e);
				}
			}
		}
		return result;
	}

	public static HttpHandler readHttpHandler(HttpHandler result, String packagePath) {
		List<String> classNames = PackageTools.getClassName(packagePath);
		for (String className : classNames) {
			try {
				Class<?> clazz = Class.forName(className);
				Object obj = clazz.newInstance();
				result = readHttpHandler(result, obj, clazz);
			} catch (Exception e) {
				log.error(e.getMessage(),e);
			}
		}
		return result;
	}

	public static HttpHandler readHttpHandler(HttpHandler result, Object obj, Class<?> clazz) {
		try {
			String contextPath = null;
			Route classRoute = clazz.getAnnotation(Route.class);
			if (classRoute != null && classRoute.value().length > 0) {
				if (StringUtils.isNotBlank(classRoute.value()[0])) {
					contextPath = classRoute.value()[0];
				}
			}
			Method[] methods = clazz.getDeclaredMethods();
			for (int i = 0; i < methods.length; i++) {
				Method method = methods[i];
				Route route = method.getAnnotation(Route.class);
				if (route != null) {
					HttpHandler handler = null;
					if (contextPath != null) {
						handler = new HttpHandler(contextPath, route, obj, method);
					} else {
						handler = new HttpHandler(route, obj, method);
					}
					if (result == null) {
						result = handler;
					} else {
						result.setNextHandler(handler);
					}
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}

		return result;
	}

	// 执行HTTP处理
	public static Resource execute(HttpHandler httpHandler, String uri, HttpServletRequest request, HttpServletResponse response,
			FileItemFactory fileItemFactory) {
		HttpHandler temp = httpHandler;
		while (temp != null) {
			if (temp.before(request, uri)) {
				Resource resource = temp.execute(request, response, new ServletFileUpload(fileItemFactory));
				if (resource == null) {
					resource = new VoidResource();
				}
				return resource;
			} else {
				temp = temp.getNextHandler();
			}
		}
		return null;
	}

}
